﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Microsoft.SharePoint;

namespace ITSP.EventReceiverConfig
{
    public interface IEventReceiverOperation
    {
        void Initialise(string url, EventReceiverConfiguration configuration);
        bool Execute();
        string GetOutput();
    }

    /// <summary>
    /// The base / concrete class implementation of the IEventReceiverOperation interface
    /// All new Event Receiver operations defined by the utilities parameters should be based off this class.
    /// </summary>
    public class EventReceiverBaseOperation : IEventReceiverOperation
    {
        protected EventReceiverConfiguration _configuration;
        protected string _operationOutput = String.Empty;
        protected string _url = String.Empty;

        #region IEventReceiverOperation Members
        public void Initialise(string url, EventReceiverConfiguration configuration)
        {
            _url = url;
            _configuration = configuration;
        }

        public bool Execute()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public string GetOutput()
        {
            return _operationOutput;
        }

        #endregion
    }

    /// <summary>
    /// Operation to list all the event receivers in a content type
    /// </summary>
    public class EventReceiverContentTypeListOperation : EventReceiverBaseOperation, IEventReceiverOperation
    {

        #region IEventReceiverOperation Members

        /// <summary>
        /// Execute the event receiver operation
        /// </summary>
        /// <returns></returns>
        public bool Execute()
        {
            bool bSuccess = false;
            try
            {
                //get access to the SPWeb object
                Uri siteUri=new Uri(_url);
                using(SPSite site=new SPSite(siteUri.ToString()))
                {
                    using(SPWeb web=site.OpenWeb(siteUri.LocalPath))
                    {
                        EventReceiverHelper helper=new EventReceiverHelper(web);
                        SPContentType contentType=helper.GetContentType(web, _configuration.EventReceiverTargetName);
                        
                        string eventReceiverOutput = String.Empty;
                        string eventReceiverDetail = String.Empty;
                        foreach(SPEventReceiverDefinition eventReceiverDefinition in contentType.EventReceivers)
                        {
                            eventReceiverDetail = String.Format("Assembly: {0}\nClass: {1}\nEventReceiverType: {2}\nName: {3}\nFull Details: {4}",
                                                    eventReceiverDefinition.Assembly, eventReceiverDefinition.Class,
                                                    eventReceiverDefinition.Type, eventReceiverDefinition.Name,eventReceiverDefinition.ToString());

                            eventReceiverOutput = String.Format("{0}\n{1}", eventReceiverOutput, eventReceiverDetail);
                        }

                        bSuccess = true;
                        if(bSuccess)
                        {
                            _operationOutput = string.Format("Event Receiver Info: \n {0}", eventReceiverOutput);
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            return bSuccess;
        }

        #endregion
    }

    /// <summary>
    /// Operation to add an event receiver to a content type
    /// </summary>
    public class EventReceiverContentTypeAddOperation : EventReceiverBaseOperation, IEventReceiverOperation
    {

        #region IEventReceiverOperation Members

        /// <summary>
        /// Execute the event receiver operation
        /// </summary>
        /// <returns></returns>
        public bool Execute()
        {
            bool bSuccess = false;
            try
            {
                //get access to the SPWeb object
                Uri siteUri = new Uri(_url);
                using (SPSite site = new SPSite(siteUri.ToString()))
                {
                    using (SPWeb web = site.OpenWeb(siteUri.LocalPath))
                    {
                        EventReceiverHelper helper = new EventReceiverHelper(web);
                        SPContentType contentType = helper.GetContentType(web, _configuration.EventReceiverTargetName);
                        bSuccess = helper.AddEventReceiver(contentType, _configuration);

                        if (bSuccess)
                        {
                            _operationOutput = string.Format("Operation Successful \n Added Event Receiver: {0} {1} to Content Type: {2}", _configuration.Assembly, _configuration.Class, contentType.Name);
                        }
                    }
                }
            }
            catch (Exception)
            {

                throw;
            }
            return bSuccess;
        }

        #endregion
    }

    /// <summary>
    /// Operation to remove an event receivers from a content type
    /// </summary>
    public class EventReceiverContentTypeRemoveOperation : EventReceiverBaseOperation, IEventReceiverOperation
    {

        #region IEventReceiverOperation Members

        public bool Execute()
        {
            bool bSuccess = false;
            try
            {
                //get access to the SPWeb object
                Uri siteUri = new Uri(_url);
                using (SPSite site = new SPSite(siteUri.ToString()))
                {
                    using (SPWeb web = site.OpenWeb(siteUri.LocalPath))
                    {
                        EventReceiverHelper helper = new EventReceiverHelper(web);
                        SPContentType contentType = helper.GetContentType(web, _configuration.EventReceiverTargetName);
                        bSuccess = helper.RemoveEventReceiver(contentType, _configuration);

                        if (bSuccess)
                        {
                            _operationOutput = string.Format("Operation Successful \n Removed Event Receiver: {0} {1} to Content Type: {2}", _configuration.Assembly, _configuration.Class, contentType.Name);
                        }
                    }
                }
            }
            catch (Exception)
            {
                
                throw;
            }
            return bSuccess;
        }

        #endregion
    }

    /// <summary>
    /// Operation to list all the event receivers in a list or document library
    /// </summary>
    public class EventReceiverListListOperation : EventReceiverBaseOperation, IEventReceiverOperation
    {

        #region IEventReceiverOperation Members

        /// <summary>
        /// Execute the event receiver operation
        /// </summary>
        /// <returns></returns>
        public bool Execute()
        {
            bool bSuccess = false;
            try
            {
                //get access to the SPWeb object
                Uri siteUri = new Uri(_url);
                using (SPSite site = new SPSite(siteUri.ToString()))
                {
                    using (SPWeb web = site.OpenWeb(siteUri.LocalPath))
                    {
                        EventReceiverHelper helper = new EventReceiverHelper(web);
                        SPList list = helper.GetList(web, _configuration.EventReceiverTargetName);

                        string eventReceiverOutput = String.Empty;
                        string eventReceiverDetail = String.Empty;
                        foreach (SPEventReceiverDefinition eventReceiverDefinition in list.EventReceivers)
                        {
                            eventReceiverDetail = String.Format("Assembly: {0}\nClass: {1}\nEventReceiverType: {2}\nName: {3}\n Full Details: {4}\n",
                                                    eventReceiverDefinition.Assembly, eventReceiverDefinition.Class,
                                                    eventReceiverDefinition.Type, eventReceiverDefinition.Name,eventReceiverDefinition.ToString());

                            eventReceiverOutput = String.Format("{0}\n{1}", eventReceiverOutput, eventReceiverDetail);
                        }

                        bSuccess = true;
                        if (bSuccess)
                        {
                            _operationOutput = string.Format("Event Receiver Info: \n {0}", eventReceiverOutput);
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            return bSuccess;
        }

        #endregion
    }

    /// <summary>
    /// Operation to add an event receivers to a list or document library
    /// </summary>
    public class EventReceiverListAddOperation : EventReceiverBaseOperation, IEventReceiverOperation
    {

        #region IEventReceiverOperation Members

        /// <summary>
        /// Execute the event receiver operation
        /// </summary>
        /// <returns></returns>
        public bool Execute()
        {
            bool bSuccess = false;
            try
            {
                //get access to the SPWeb object
                Uri siteUri = new Uri(_url);
                using (SPSite site = new SPSite(siteUri.ToString()))
                {
                    using (SPWeb web = site.OpenWeb(siteUri.LocalPath))
                    {
                        EventReceiverHelper helper = new EventReceiverHelper(web);
                        SPList list = helper.GetList(web, _configuration.EventReceiverTargetName);
                        bSuccess = helper.AddEventReceiver(list, _configuration);

                        if (bSuccess)
                        {
                            _operationOutput = string.Format("Operation Successful \n Added Event Receiver: {0} {1} to List: {2}", _configuration.Assembly, _configuration.Class, list.Title);
                        }
                    }
                }
            }
            catch (Exception)
            {

                throw;
            }
            return bSuccess;
        }

        #endregion
    }

    /// <summary>
    /// Operation to remove an event receivers from a list or document library
    /// </summary>
    public class EventReceiverListRemoveOperation : EventReceiverBaseOperation, IEventReceiverOperation
    {

        #region IEventReceiverOperation Members

        public bool Execute()
        {
            bool bSuccess = false;
            try
            {
                //get access to the SPWeb object
                Uri siteUri = new Uri(_url);
                using (SPSite site = new SPSite(siteUri.ToString()))
                {
                    using (SPWeb web = site.OpenWeb(siteUri.LocalPath))
                    {
                        EventReceiverHelper helper = new EventReceiverHelper(web);
                        SPList list = helper.GetList(web, _configuration.EventReceiverTargetName);
                        bSuccess = helper.RemoveEventReceiver(list, _configuration);

                        if (bSuccess)
                        {
                            _operationOutput = string.Format("Operation Successful \n Removed Event Receiver: {0} {1} to List: {2}", _configuration.Assembly, _configuration.Class, list.Title);
                        }
                    }
                }
            }
            catch (Exception)
            {

                throw;
            }
            return bSuccess;
        }

        #endregion
    }

    /// <summary>
    /// Operation to list all the event receivers in an assembly
    /// </summary>
    public class EventReceiverAssemblyListOperation : EventReceiverBaseOperation, IEventReceiverOperation
    {

        #region IEventReceiverOperation Members

        /// <summary>
        /// Execute the event receiver operation
        /// </summary>
        /// <returns></returns>
        public bool Execute()
        {
            bool bSuccess = false;
            try
            {
                //get access to the SPWeb object
                Uri siteUri = new Uri(_url);
                using (SPSite site = new SPSite(siteUri.ToString()))
                {
                    using (SPWeb web = site.OpenWeb(siteUri.LocalPath))
                    {
                        EventReceiverHelper helper = new EventReceiverHelper(web);
                        List<EventReceiverClassInfo> listEventReceiverClasses = helper.GetEventReceiverObjectsFromAssembly(_configuration.Assembly);

                        string eventReceiverOutput = String.Empty;
                        StringBuilder outputBuilder = new StringBuilder();
                        foreach (EventReceiverClassInfo classInfo in listEventReceiverClasses)
                        {
                            outputBuilder.AppendLine(classInfo.DisplayInfo());
                            outputBuilder.AppendLine("");
                        }
                        eventReceiverOutput = outputBuilder.ToString();

                        bSuccess = true;
                        if (bSuccess)
                        {
                            _operationOutput = string.Format("Event Receiver Info: \n\r {0}", eventReceiverOutput);
                        }
                    }
                }
            }
            catch (System.IO.FileNotFoundException fileex)
            {
                throw;
            }
            catch (Exception)
            {
                throw;
            }
            return bSuccess;
        }

        #endregion
    }

    /// <summary>
    /// Class which implements a factory pattern to create the appropriate <see cref="IEventReceiverOperation"/>
    /// based on the parameters specified by the utility.
    /// </summary>
    public class EventReceiverOperationFactory
    {
        public EventReceiverOperationFactory()
        {

        }

        public static IEventReceiverOperation GetOperationInstance(ProgramControl.Mode mode, string url, EventReceiverConfiguration configuration)
        {
            IEventReceiverOperation operation = null;
            try
            {
                switch (mode)
                {
                    case ProgramControl.Mode.List:
                        //check the type
                        switch (configuration.EventReceiverTargetType.ToLower())
                        {
                            case "list":
                                operation = new EventReceiverListListOperation();
                                operation.Initialise(url,configuration);
                                break;
                            case "contenttype":
                                operation = new EventReceiverContentTypeListOperation();
                                operation.Initialise(url, configuration);
                                break;
                            case "assembly":
                                operation = new EventReceiverAssemblyListOperation();
                                operation.Initialise(url, configuration);
                                break;
                        }
                        break;
                    case ProgramControl.Mode.Add:
                        switch (configuration.EventReceiverTargetType.ToLower())
                        {
                            case "list":
                                operation = new EventReceiverListAddOperation();
                                operation.Initialise(url, configuration);
                                break;
                            case "contenttype":
                                operation = new EventReceiverContentTypeAddOperation();
                                operation.Initialise(url, configuration);
                                break;
                        }
                        break;
                    case ProgramControl.Mode.Remove:
                        switch (configuration.EventReceiverTargetType.ToLower())
                        {
                            case "list":
                                operation = new EventReceiverListRemoveOperation();
                                operation.Initialise(url, configuration);
                                break;
                            case "contenttype":
                                operation = new EventReceiverContentTypeRemoveOperation();
                                operation.Initialise(url, configuration);
                                break;
                        }
                        break;
                }
            }
            catch (Exception)
            {


                throw;
            }

            return operation;
        }

    }
    
}
